home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_200 / 227_01 / graf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-02-07  |  41.1 KB  |  1,502 lines

  1. /*
  2.  * g r a f . c
  3.  * -----------
  4.  * This is the hardware-independant, high-level part of the compatible
  5.  * graphics library.
  6.  *
  7.  * update history
  8.  * --------------
  9.  * May, 27. 1987    Use extended functionality of the hercules low-level
  10.  *                  driver. This driver now allows to write 8 pixel with
  11.  *                  one function call, what dramatically decraeses execution
  12.  *                  time.
  13.  * May, 30. 1987    Same as above for the ega low-level driver.
  14.  *                  Also stack space and execution time needed by paint
  15.  *                  reduced, theirby removing a undocumented function
  16.  *                  (paintfil).
  17.  * May, 31. 1987    Function "polyline" added; begin use of graphics error
  18.  *                  system.
  19.  * Jul, 25. 1987    Begin implemention on reverse-color functions.
  20.  * Aug, 30. 1987    Function fellipsis implemented.
  21.  *            Implemention of reverse-color funtions cancelled,
  22.  *            begin implemention of the more powerful write mode
  23.  *            system (includes reverse colors).
  24.  * Nov, 14. 1987    wrtpixel function added.
  25.  *
  26.  * Written by       Rainer Gerhards
  27.  *                  Petronellastr. 6
  28.  *                  D-5112 Baesweiler
  29.  *                  West Germany
  30.  *                  Phone (49) 2401 - 1601
  31.  */
  32.  
  33. /*
  34.  * Define library implemention mode - forbidden for user!
  35.  */
  36. #define LIB_MODE 2            /* I am the Master module!    */
  37.  
  38. #include <stdio.h>
  39. #include <dos.h>
  40. #include <math.h>
  41. #ifdef     __TURBOC__
  42.   #include <stdlib.h>
  43. #endif
  44.  
  45. #include "graphics.h"
  46.  
  47. #define last3bit(x) ((x) &  0x0007)
  48. #define exclst3b(x) ((x) & ~0x0007)
  49.  
  50. /*
  51.  * global data-items (the user program may access these items) ...
  52.  * are 'til now (Jun, 20. 1987) defined in "graphics.h"!
  53.  */
  54.  
  55. /*
  56.  * The following static items are used by the global/local coordinate system.
  57.  */
  58. static float x_start = 0.0;   /* Beginning x coordinate     */
  59. static float x_step  = 1.0;   /* size of a logical x - unit */
  60. static float y_start = 0.0;   /* Beginning y coordinate     */
  61. static float y_step  = 1.0;   /* size of a logical y - unit */
  62.  
  63. /*
  64.  * function prototypes (if allowed)
  65.  */
  66. #ifdef    USEPROTT
  67. extern void    hline(int, int, int, int);
  68. extern int    paintfil(int, int);
  69. extern int    selcolor(int, int);
  70. extern void    fline(int, int, int, int);
  71. extern void    ffillbox(int, int, int, int);
  72. #endif
  73.  
  74. /*
  75.  *    Auxiliary function set,
  76.  *    the following functions are only called internally from other
  77.  *    functions within this module. This function set duplicates most
  78.  *    of the main function set functions, with the execpetion that
  79.  *    the functions containd in the auxiliary perform their operation
  80.  *    in the non-standard write modes (writemod != WM_NORM).
  81.  *
  82.  *    This improves speed dramatically, but unfortunatly needs a lot
  83.  *    of memory. If anyone think's that the memory requirements are to
  84.  *    big, please contact me. I then will implement an much smaller (but
  85.  *    also much slower) function set. I don't implement it today, because
  86.  *    I see no reason for it. I hope the CP/M programmers will share this
  87.  *    opinion.
  88.  */
  89.  
  90. int    selcolor(x, y)
  91. int    x, y;
  92. /*
  93.  * name        selcolor
  94.  *
  95.  * synopsis    color = selcolor(x, y);
  96.  *        int    x, y;        pixel coordinate
  97.  *
  98.  * description    This function selects the drawing color acording to the
  99.  *        current write mode and the requested color.
  100.  *
  101.  * Note        The requested color must be contained in field curcolor!
  102.  */
  103. {
  104. register int    retcolor;        /* selected color        */
  105.  
  106. retcolor = getpixel(x, y);
  107. switch(writemod)
  108.     {
  109.     case WM_XOR:    retcolor ^= curcolor;
  110.             break;
  111.     case WM_AND:    retcolor &= curcolor;
  112.             break;
  113.     case WM_OR:    retcolor |= curcolor;
  114.             break;
  115.     case WM_INV:    retcolor = ~retcolor;
  116.             break;
  117.     }
  118. return(retcolor);
  119. }
  120.  
  121.  
  122. static void    fline(x1, y1, x2, y2)
  123. int x1, y1;
  124. int x2, y2;
  125. /**
  126. * name          fline
  127. *
  128. * synopsis      line(x1, y1, x2, y2);
  129. *               int x1, y1;            starting coordinate
  130. *               int x2, y2;            ending coordinate
  131. *
  132. * description   This function draws a line of "color" between the
  133. *               starting (x1, y1) and ending (x2, y2) coordinate.
  134. **/
  135. {
  136. register int count;      /* loop counter, highest difference */
  137. register int berr;
  138. int ix, ox, iy, oy;
  139. int zwsp;                /* to swap x2 and y2 */
  140.  
  141. if(y1 == y2)              /* horizontal line? */
  142.   {
  143.   if(x1 > x2)
  144.     {
  145.     zwsp = x1;
  146.     x1 = x2;
  147.     x2 = zwsp;
  148.     }
  149.   for( ; x1 <= x2 ; ++x1)
  150.       setpixel(x1, y1, selcolor(x1, y1));
  151.   }
  152. else if(x1 == x2)          /* vertikal line? */
  153.   {
  154.   if(y1 > y2)
  155.     {
  156.     zwsp = y1;
  157.     y1 = y2;
  158.     y2 = zwsp;
  159.     }
  160.   for( ; y1 <= y2 ; y1++)
  161.       setpixel(x1, y1, selcolor(x1, y1));
  162.   }
  163. else
  164.   {
  165.   if((x2 -= x1) > 0)  /* x difference */
  166.     ix = ox = 1;      /* add in loop */
  167.   else
  168.     {
  169.     ix = ox = -1;     /* subtract in loop */
  170.     x2 = -x2;         /* use absolute difference! */
  171.     }
  172.   if((y2 -= y1) > 0)  /* y difference */
  173.     iy = oy = 1;      /* add in loop */
  174.   else
  175.     {
  176.     iy = oy = -1;     /* subtract in loop */
  177.     y2 = -y2;         /* use absolute difference! */
  178.     }
  179.   if(x2 >= y2)        /* select inner/outer loop to add/subtract */
  180.     {
  181.     zwsp = x2;        /* swap x2, y2 */
  182.     x2 = y2;
  183.     y2 = zwsp;
  184.     ix =              /* modify x-coordinate in outer   */
  185.     oy = 0;           /* and y-coordinate in inner loop */
  186.     }
  187.   else
  188.     iy =              /* modify y-coordinate in outer   */
  189.     ox = 0;           /* and x-coordinate in inner loop */
  190.   berr = (x2 << 1) - y2;
  191.   count = y2 + 1;
  192.   do   /* main loop, draws line */
  193.     {
  194.     setpixel(x1, y1, selcolor(x1, y1));
  195.     if(berr > 0)
  196.       {
  197.       berr += (x2 - y2) << 1;
  198.       x1 += ix;
  199.       y1 += iy;
  200.       }
  201.     else
  202.       berr += x2 << 1;
  203.     x1 += ox;
  204.     y1 += oy;
  205.     }
  206.   while(--count > 0);  /* warning: do ... while! */
  207.   }
  208. }
  209.  
  210.  
  211. static void    ffillbox(x1, y1, x2, y2)
  212. register int x1;
  213. int y1;
  214. int x2, y2;
  215. /**
  216. * name          fillbox
  217. *
  218. * synopsis      fillbox(x1, y1, x2, y2, color);
  219. *               int x1, y1;            upper left corner
  220. *               int x2, y2;            lower right corner
  221. *               int color;             fill color
  222. *
  223. * description   This function fills a given box with the specified color.
  224. *               The box is specified through the upper left (x1, y1) and
  225. *               the lower right (x2, y2) corner.
  226. *               This function is the counterpart to box, which draws the
  227. *               border.
  228. **/
  229. {
  230. int zwsp;                /* to swap coordinates        */
  231. register int yt;            /* temporary y, inner loop    */
  232.  
  233. if(x1 > x2)
  234.   {
  235.   zwsp = x1;
  236.   x1 = x2;
  237.   x2 = zwsp;
  238.   }
  239. if(y1 > y2)
  240.   {
  241.   zwsp = y1;
  242.   y1 = y2;
  243.   y2 = zwsp;
  244.   }
  245. for( ; x1 <= x2 ; ++x1)                /* x loop        */
  246.   for(yt = y1 ; yt <= y2 ; ++yt)        /* y loop        */
  247.     setpixel(x1, yt, selcolor(x1, yt));
  248. }
  249.  
  250.  
  251. static void fcircle(x, y, radius, aspect)
  252. register int x, y;
  253. int radius;
  254. double aspect;
  255. /**
  256. * name          circle
  257. *
  258. * synopsis      circle(x, y, radius, color, aspect)
  259. *               int x, y;              center coordinate
  260. *               int radius;            circle radius
  261. *               double aspect;         aspect ratio
  262. *
  263. * description   This function draws a circle.
  264. **/
  265. {
  266. long asp;                /* use internal long - its faster */
  267. unsigned int invrad;     /* inverse radius - grows form 0 to radius/2 */
  268. int decision;            /* controls decrement of radius */
  269. int tmp;                 /* temporary to modify desicion */
  270. unsigned long offs;      /* compute y-offset */
  271. unsigned int offsi;      /* result y-offset (faster then long!) */
  272. unsigned int round;      /* used to round (y * asp) / 256 */
  273.  
  274. asp = (long) (aspect * 256);   /* using long is much faster! */
  275. invrad = 0;
  276. decision = 3 - (radius << 1);
  277. while(invrad <= radius)
  278.   {
  279.   offs = radius * asp;
  280.   round = ((unsigned int) (offs & 0x00000080)) >> 7;
  281.   offsi = (unsigned int) ((offs >> 8) + round); /* divide by 256 (rounded) */
  282.   setpixel(x + invrad, y + offsi, selcolor(x + invrad, y + offsi));
  283.   setpixel(x + invrad, y - offsi, selcolor(x + invrad, y - offsi));
  284.   setpixel(x - invrad, y - offsi, selcolor(x - invrad, y - offsi));
  285.   setpixel(x - invrad, y + offsi, selcolor(x - invrad, y + offsi));
  286.   offs = invrad * asp;
  287.   round = ((unsigned int) (offs & 0x00000080)) >> 7;
  288.   offsi = (unsigned int) ((offs >> 8) + round); /* divide by 256 (rounded) */
  289.   setpixel(x + radius, y + offsi, selcolor(x + invrad, y + offsi));
  290.   setpixel(x + radius, y - offsi, selcolor(x + invrad, y - offsi));
  291.   setpixel(x - radius, y - offsi, selcolor(x - invrad, y - offsi));
  292.   setpixel(x - radius, y + offsi, selcolor(x - invrad, y + offsi));
  293.   if(decision >= 0)  /* decrement radius? */
  294.     {
  295.     tmp = ((invrad - radius) << 2) + 10;
  296.     radius--;
  297.     }
  298.   else
  299.     tmp = (invrad << 2) + 6;
  300.   decision += tmp;
  301.   invrad++;
  302.   }
  303. }
  304.  
  305.  
  306. #if 0
  307. #ifdef USEVOID
  308. void
  309. #endif
  310. paint(x, y, paintclr, border)
  311. int x, y;
  312. int paintclr;
  313. int border;
  314. /**
  315. * name          paint
  316. *
  317. * synopsis      paint(x, y, paintclr, border)
  318. *               int x, y;              coordinate of a point within the area
  319. *               int paintclr;          the color used to paint
  320. *               int border;            is the color of the border defining the
  321. *                                      area
  322. *
  323. * description   This function paints an area. The area is defined by a border
  324. *               of a specified color ("border") and the coordinate of one
  325. *               pixel within the area (x, y). The color used to paint is
  326. *               given in "paintclr".
  327. *               This function ueses several subroutines and a recursive
  328. *               algorithm! It's only the "initializer", the main work is
  329. *               performed by the other Routines.
  330. **/
  331. {
  332. pcolor = paintclr;  /* Initialize static variables */
  333. bcolor = border;
  334. #if defined(EGAGRAF)
  335. setewm2();
  336. #endif
  337. paintfil(x, y);     /* start recursive algorithms */
  338. #if defined(EGAGRAF)
  339. rsestdwm();
  340. #endif
  341. }
  342.  
  343. static paintfil(x, y)
  344. int x, y;
  345. /**
  346. * name          paintfil
  347. *
  348. * synopsis      paintfil(x, y);
  349. *               int x, y;              coordinate of a point to process
  350. *
  351. * description   This function is only internal to paint, and such ist subject
  352. *               to change without notice!
  353. *               This is the main painting algorithm. It's called recursively
  354. *               every new cycle.
  355. **/
  356. {
  357. int x_right;
  358. int x_left;
  359. static int color;     /* red pixelcolor (by getpixel) */
  360.  
  361. /*
  362.  * name          fillnew
  363.  *
  364.  * synopsis      paintfil(x, y, x_min);
  365.  *               int x, y;
  366.  *               int x_min;
  367.  *
  368.  * description   Select new fill area. This was macro was in the first release
  369.  *               of the library a function. But the whole procedure paint()
  370.  *               need so a lot of stack space, that it is now implemented as
  371.  *               a macro, saving 2 Byte (or 4 Byte in the large model) of
  372.  *               stack space per call. This reduces space requirements dra-
  373.  *               matically. In addition 2 Byte stack space are now freed,
  374.  *               which were previously allocated to the auto variable color,
  375.  *               which is now common to paintfil and fillnew (it's now static,
  376.  *               too).
  377.  *
  378.  * warning       because it's now a macro, there should be no side-effects in
  379.  *               the function arguments!
  380.  */
  381. static int fillnewx;
  382. #if defined(EGAGRAF)
  383.   #define fillnew(x,y,x_min)\
  384.   {\
  385.   fillnewx = (x);\
  386.   while(fillnewx >= (x_min))\
  387.     {\
  388.     color = qgetpix(fillnewx, (y));\
  389.     if((color != pcolor) && (color != bcolor))\
  390.       fillnewx = paintfil(fillnewx, (y));\
  391.     fillnewx--;\
  392.     }\
  393.   }
  394. #else /* EGAGRAF not defined */
  395.   #define fillnew(x,y,x_min)\
  396.   {\
  397.   fillnewx = (x);\
  398.   while(fillnewx >= (x_min))\
  399.     {\
  400.     color = getpixel(fillnewx, (y));\
  401.     if((color != pcolor) && (color != bcolor))\
  402.       fillnewx = paintfil(fillnewx, (y));\
  403.     fillnewx--;\
  404.     }\
  405.   }
  406. #endif
  407.  
  408. x_right = x_left = x;
  409. #if defined(EGAGRAF)
  410. qsetpix(x, y, pcolor);
  411. #else
  412. setpixel(x, y, pcolor);
  413. #endif
  414. while((++x_right) <= X_HIGH)
  415.   {
  416.   #if defined(EGAGRAF)
  417.   color = qgetpix(x_right, y);
  418.   #else
  419.   color = getpixel(x_right, y);
  420.   #endif
  421.   if((color == pcolor) || (color == bcolor))
  422.     break;  /* exit loop */
  423.   }
  424. x_right--;
  425. while((--x_left) >= X_LOW)
  426.   {
  427.   #if defined(EGAGRAF)
  428.   color = qgetpix(x_left, y);
  429.   #else
  430.   color = getpixel(x_left, y);
  431.   #endif
  432.   if((color == pcolor) || (color == bcolor))
  433.     break;  /* exit loop */
  434.   }
  435. x_left++;
  436. hline(x_left,x_right,y,pcolor);  /* fill area */
  437. if(--y >= Y_LOW)
  438.   fillnew(x_right, y, x_left);
  439. y += 2;
  440. if(y <= Y_HIGH)
  441.   fillnew(x_right, y, x_left);
  442. return(x_left);
  443. #undef fillnew  /* local to paintfil */
  444. }
  445. #endif
  446.  
  447.  
  448. #ifdef USEVOID
  449. void
  450. #endif
  451. fstellipsis(x, y, rx, ry, ws, we)
  452. int x, y;
  453. int rx, ry;
  454. int ws, we;
  455. /**
  456. * name          ellipsis
  457. *
  458. * synopsis      ellipsis(x, y, rx, ry, ws, we)
  459. *               int x, y      center coordinate
  460. *               int rx        x - 'radius'
  461. *               int ry        y - 'radius'
  462. *               int ws        begin angle 0..360
  463. *               int we        end  angle 0..360
  464. *
  465. * description   This function draws any sort of ellipsis. It is often called
  466. *               circle, but I think this name should better be reserverd for
  467. *               a function, which only draws a FULL circle (see above).
  468. *               This function may not only draw a circle or any possible
  469. *               ellipsis, it is also capable of drawing only parts of them.
  470. *               This feature is often used in pie-charts. Because of its
  471. *               great flexibility, this function ist much slower than circle.
  472. *               If you only want a full circle (or ellipsis) you should call
  473. *               circle.
  474. **/
  475. {
  476. #define round(x) (int) (x + .5)
  477. register int xt, yt;            /* temporary coordinates    */
  478. int w;
  479. int drawlin;
  480. float begarc, endarc;
  481. float wb;
  482. float step;
  483.  
  484. drawlin = 0;
  485. if(rx < 0)
  486.   rx = -rx;
  487. if(ry < 0)
  488.   ry = -ry;
  489. if(ws < 0)
  490.   {
  491.   ws = -ws;
  492.   drawlin = -1;
  493.   }
  494. while(ws > 360)
  495.   ws = ws - 360;
  496. if(we < 0)
  497.   {
  498.   we = -we;
  499.   drawlin = -1;
  500.   }
  501. while(we > 360)
  502.   we = we - 360;
  503. if(ws > we)
  504.   {
  505.   w = ws;
  506.   ws = we;
  507.   we = w;
  508.   }
  509. step = (float) (rx + ry) / 50.0;
  510. begarc = ws * step;            /* beginning angle */
  511. endarc = we * step;            /* ending angle */
  512. step = PI_D_180 / step;            /* compute new step (radiant) */
  513. begarc = step * begarc;            /* beginning angle in radiant */
  514. endarc = step * endarc;            /* ending angle in radiant */
  515. for(wb = begarc ; wb <= endarc ; wb += step)
  516.   {
  517.   xt = round(x + rx * cos(wb));
  518.   yt = round(y - ry * sin(wb));
  519.   setpixel(xt, yt, selcolor(xt, yt));
  520.   }
  521. if(drawlin && !(ws == 0 && we == 360)) /* must draw line? */
  522.   {                                    /* Yes!            */
  523.   xt = round(x + rx * cos(begarc));
  524.   yt = round(y - ry * sin(begarc));
  525.   line(xt, yt, x, y, selcolor(xt, yt));
  526.   xt = round(x + rx * cos(endarc));
  527.   yt = round(y - ry * sin(endarc));
  528.   line(xt, yt, x, y, selcolor(xt, yt));
  529.   }
  530. }
  531.  
  532.  
  533. static void ffellipsis(x, y, rx, ry, ws, we)
  534. int x, y;
  535. int rx, ry;
  536. int ws, we;
  537. /*
  538.  * name          fellipsis
  539.  *
  540.  * synopsis      fellipsis(x, y, rx, ry, ws, we, color)
  541.  *               int x, y      center coordinate
  542.  *               int rx        x - 'radius'
  543.  *               int ry        y - 'radius'
  544.  *               int ws        begin angle 0..360
  545.  *               int we        end  angle 0..360
  546.  *
  547.  * description   This function is much like ellipsis(), but it's faster because
  548.  *         it useses only full angles to draw the ellipsis. For a
  549.  *         description see under ellipsis.
  550.  */
  551. {
  552. register int    xt, yt;            /* temporary coordinates    */
  553. int w;
  554. int drawlin;
  555.  
  556. drawlin = 0;
  557. if(rx < 0)
  558.   rx = -rx;
  559. if(ry < 0)
  560.   ry = -ry;
  561. if(ws < 0)
  562.   {
  563.   ws = -ws;
  564.   drawlin = -1;
  565.   }
  566. while(ws > 360)
  567.   ws = ws - 360;
  568. if(we < 0)
  569.   {
  570.   we = -we;
  571.   drawlin = -1;
  572.   }
  573. while(we > 360)
  574.   we = we - 360;
  575. if(ws > we)
  576.   {
  577.   w = ws;
  578.   ws = we;
  579.   we = w;
  580.   }
  581. for(w = ws ; w <= we ; ++w)
  582.   {
  583.   xt = round(x + rx * intcos(w));
  584.   yt = round(y - ry * intsin(w));
  585.   setpixel(xt, yt, selcolor(xt, yt));
  586.   }
  587. if(drawlin && !(ws == 0 && we == 360)) /* must draw line? */
  588.   {                                    /* Yes!            */
  589.   xt = round(x + rx * intcos(ws));
  590.   yt = round(y - ry * intsin(ws));
  591.   line(xt, yt, x, y, selcolor(xt, yt));
  592.   xt = round(x + rx * intcos(we));
  593.   yt = round(y - ry * intsin(we));
  594.   line(xt, yt, x, y, selcolor(xt, yt));
  595.   }
  596. }
  597. #undef    round
  598.  
  599.  
  600. /*
  601.  *    Main function set,
  602.  *    these functions are called by the user. Each function determines for
  603.  *    itself which auxiliary function is to call if writemod != WM_NORM.
  604.  *    All of the following functions are highly optimized.
  605.  */
  606.  
  607.  
  608. int        setwm(mode)
  609. WRITEMOD    mode;
  610. /*
  611.  * name        setwm
  612.  *
  613.  * synopsis    setwm(mode);
  614.  *        WRITEMOD mode;            new write mode
  615.  *
  616.  * description    This function sets the library write mode. All write
  617.  *        operations are performed in respect to the current
  618.  *        write mode.
  619.  *        For a list of currently supported write modes see the
  620.  *        definition of WRITEMOD in graphics.h!
  621.  */
  622. {
  623. int    state;
  624.  
  625. if((mode >= WM_MIN) && (mode <= WM_MAX))
  626.     {
  627.     writemod = mode;
  628.     state = OK;
  629.     }
  630. else
  631.     {
  632.     gr_error = GE_WMWRG;
  633.     state = WRONG;
  634.     }
  635. return(state);
  636. }
  637.  
  638.  
  639. void wrtpixel(x, y, color)
  640. register int x, y;
  641. int color;
  642. /*
  643.  * name          wrtpixel
  644.  *
  645.  * synopsis      wrtpixel(x, y, color);
  646.  *               int x, y;              pixel coordinate
  647.  *               int color;             pixel color
  648.  *
  649.  * description   This function sets a pixel in the given color at the
  650.  *             specified coordinate. The pixel is set in respect to
  651.  *         the current write mode.
  652.  */
  653. {
  654. curcolor = color;
  655. setpixel(x, y, selcolor(x, y));
  656. }
  657.  
  658.  
  659. static void hline(x1, x2, y, color)
  660. int x1;
  661. int x2;
  662. int y;
  663. int color;
  664. /*
  665.  * name          hline
  666.  *
  667.  * synopsis      line(x1, x2, y, color);
  668.  *               int x1;                starting x-coordinate
  669.  *               int x2;                ending x-coordinate
  670.  *               int y;                 line y-coordinate
  671.  *               int color;             line color
  672.  *
  673.  * description   This function draws a horizontal line of "color" between the
  674.  *               starting (x1, y) and ending (x2, y) coordinates.
  675.  *
  676.  * warning       This function is only for internal use. It requires that ega
  677.  *               write mode 2 is set, if the ega device is used. X1 must be
  678.  *               less than or equal to x2.
  679.  */
  680. {
  681. #if defined(HERCGRAF) || defined(EGAGRAF)
  682.   register int xt;      /* used for horizontal, bytewise line-drawing */
  683. #endif
  684.  
  685. #if defined(HERCGRAF) || defined(EGAGRAF)
  686. if((x2 - x1) >= 10)
  687.   {
  688.   color = (color & 1) ? 0xff : 0x00;   /* set fill byte                   */
  689.   if((xt = last3bit(x1)))              /* x-coordinate on 8 bit boundery? */
  690.     for(xt = 8 - xt ; xt ; ++x1, --xt) /* no - draw before 8-bit boundery */
  691.       #if defined(EGAGRAF)
  692.         qsetpix(x1, y, color);
  693.       #else
  694.         setpixel(x1, y, color);
  695.       #endif
  696.   xt = last3bit(x2) + 1; /* xt contains now the nbr of pixels to draw after */
  697.   x2 = exclst3b(x2) - 8; /* byte-draws are completed. x2 = nbr of byte-draws*/
  698.   for( ; x1 <= x2 ; x1 += 8)  /* perform byte drawing */
  699.     #if defined(EGAGRAF)
  700.       setbyte(x1, y, color, 0xff);  /* fill whole byte */
  701.     #else
  702.       setbyte(x1, y, color);
  703.     #endif
  704.   for( ; xt ; ++x1, --xt)  /* draw after 8-bit boundery */
  705.     #if defined(EGAGRAF)
  706.       qsetpix(x1, y, color);
  707.     #else
  708.       setpixel(x1, y, color);
  709.     #endif
  710.   }
  711. else
  712.   { /* less than 10 bit - use normal algorithm */
  713. #endif
  714.   for( ; x1 <= x2 ; ++x1)
  715.     #if defined(EGAGRAF)
  716.       qsetpix(x1, y, color);
  717.     #else
  718.       setpixel(x1, y, color);
  719.     #endif
  720. #if defined(HERCGRAF) || defined(EGAGRAF)
  721.   }
  722. #endif
  723. }
  724.  
  725.  
  726. void line(x1, y1, x2, y2, color)
  727. int x1, y1;
  728. int x2, y2;
  729. int color;
  730. /**
  731. * name          line
  732. *
  733. * synopsis      line(x1, y1, x2, y2, color);
  734. *               int x1, y1;            starting coordinate
  735. *               int x2, y2;            ending coordinate
  736. *               int color;             line color
  737. *
  738. * description   This function draws a line of "color" between the
  739. *               starting (x1, y1) and ending (x2, y2) coordinate.
  740. **/
  741. {
  742. register int count;      /* loop counter, highest difference */
  743. register int berr;
  744. int ix, ox, iy, oy;
  745. int zwsp;                /* to swap x2 and y2 */
  746.  
  747. if(writemod != WM_NORM)
  748.   {
  749.   curcolor = color;
  750.   fline(x1, y1, x2, y2);
  751.   }
  752. else
  753.   {
  754.   #if defined(EGAGRAF)
  755.   setewm2();
  756.   #endif
  757.   if(y1 == y2)              /* horizontal line? */
  758.     {
  759.     if(x1 > x2)
  760.       {
  761.       zwsp = x1;
  762.       x1 = x2;
  763.       x2 = zwsp;
  764.       }
  765.     hline(x1, x2, y1, color); /* draw the line */
  766.     }
  767.   else if(x1 == x2)          /* vertikal line? */
  768.     {
  769.     if(y1 > y2)
  770.       {
  771.       zwsp = y1;
  772.       y1 = y2;
  773.       y2 = zwsp;
  774.       }
  775.     for( ; y1 <= y2 ; y1++)
  776.       #if defined(EGAGRAF)
  777.     qsetpix(x1, y1, color);
  778.       #else
  779.     setpixel(x1, y1, color);
  780.       #endif
  781.     }
  782.   else
  783.     {
  784.     if((x2 -= x1) > 0)  /* x difference */
  785.       ix = ox = 1;      /* add in loop */
  786.     else
  787.       {
  788.       ix = ox = -1;     /* subtract in loop */
  789.       x2 = -x2;         /* use absolute difference! */
  790.       }
  791.     if((y2 -= y1) > 0)  /* y difference */
  792.       iy = oy = 1;      /* add in loop */
  793.     else
  794.       {
  795.       iy = oy = -1;     /* subtract in loop */
  796.       y2 = -y2;         /* use absolute difference! */
  797.       }
  798.     if(x2 >= y2)        /* select inner/outer loop to add/subtract */
  799.       {
  800.       zwsp = x2;        /* swap x2, y2 */
  801.       x2 = y2;
  802.       y2 = zwsp;
  803.       ix =              /* modify x-coordinate in outer   */
  804.       oy = 0;           /* and y-coordinate in inner loop */
  805.       }
  806.     else
  807.       iy =              /* modify y-coordinate in outer   */
  808.       ox = 0;           /* and x-coordinate in inner loop */
  809.     berr = (x2 << 1) - y2;
  810.     count = y2 + 1;
  811.     do   /* main loop, draws line */
  812.       {
  813.       #if defined(EGAGRAF)
  814.     qsetpix(x1, y1, color);
  815.       #else
  816.     setpixel(x1, y1, color);
  817.       #endif
  818.       if(berr > 0)
  819.     {
  820.     berr += (x2 - y2) << 1;
  821.     x1 += ix;
  822.     y1 += iy;
  823.     }
  824.       else
  825.     berr += x2 << 1;
  826.       x1 += ox;
  827.       y1 += oy;
  828.       }
  829.     while(--count > 0);  /* warning: do ... while! */
  830.     }
  831.   #if defined(EGAGRAF)
  832.   rsestdwm();
  833.   #endif
  834.   }
  835. }
  836.  
  837.  
  838. #ifdef USEVOID
  839. void
  840. #endif
  841. box(x1, y1, x2, y2, color)
  842. int x1, y1;
  843. int x2, y2;
  844. int color;
  845. /**
  846. * name          box
  847. *
  848. * synopsis      box(x1, y1, x2, y2, color);
  849. *               int x1, y1;            upper left corner
  850. *               int x2, y2;            lower right corner
  851. *               int color;             border color
  852. *
  853. * description   This function draws a border of "color" covering the
  854. *               given box. The box is specified through the upper
  855. *               left (x1, y1) and to lower right (x2, y2) corner. The
  856. *               box itself isn't modified (e. g. must be cleared explicitly).
  857. **/
  858. {
  859. line(x1, y1, x1, y2, color);  /* right line  */
  860. line(x1, y2, x2, y2, color);     /* bottom line */
  861. line(x2, y2, x2, y1, color);  /* left line   */
  862. line(x1, y1, x2, y1, color);     /* top line    */
  863. }
  864.  
  865.  
  866. void fillbox(x1, y1, x2, y2, color)
  867. int x1, y1;
  868. int x2, y2;
  869. int color;
  870. /**
  871. * name          fillbox
  872. *
  873. * synopsis      fillbox(x1, y1, x2, y2, color);
  874. *               int x1, y1;            upper left corner
  875. *               int x2, y2;            lower right corner
  876. *               int color;             fill color
  877. *
  878. * description   This function fills a given box with the specified color.
  879. *               The box is specified through the upper left (x1, y1) and
  880. *               the lower right (x2, y2) corner.
  881. *               This function is the counterpart to box, which draws the
  882. *               border.
  883. **/
  884. {
  885. int zwsp;                /* to swap coordinates        */    
  886. register int yt;            /* temporary y, inner loop    */
  887. #if defined(HERCGRAF) || defined(EGAGRAF)
  888. register int xt;            /* temporary x, inner loop    */
  889. #endif
  890.  
  891. if(writemod != WM_NORM)
  892.   {
  893.   curcolor = color;
  894.   ffillbox(x1, y1, x2, y2);
  895.   }
  896. else
  897.   {
  898.   #if defined(EGAGRAF)
  899.   setewm2();
  900.   #endif
  901.   if(x1 > x2)
  902.     {
  903.     zwsp = x1;
  904.     x1 = x2;
  905.     x2 = zwsp;
  906.     }
  907.   if(y1 > y2)
  908.     {
  909.     zwsp = y1;
  910.     y1 = y2;
  911.     y2 = zwsp;
  912.     }
  913.   #if defined(HERCGRAF) || defined(EGAGRAF)
  914.   if((x2 - x1) >= 10)
  915.     {
  916.     color = (color & 1) ? 0xff : 0x00;   /* set fill byte                   */
  917.     if((xt = last3bit(x1)))              /* x-coordinate on 8 bit boundery? */
  918.       for(xt = 8 - xt ; xt ; x1++, xt--) /* no - draw before 8-bit boundery */
  919.     for(yt = y1 ; yt <= y2 ; yt++)
  920.       #if defined(EGAGRAF)
  921.         qsetpix(x1, yt, color);
  922.       #else
  923.         setpixel(x1, yt, color);
  924.       #endif
  925.     xt = last3bit(x2) + 1; /* xt contains now the nbr of pixels to draw after */
  926.     x2 = exclst3b(x2) - 8; /* byte-draws are completed. x2 = nbr of byte-draws*/
  927.     for( ; x1 <= x2 ; x1 += 8)  /* perform byte drawing */
  928.       for(yt = y1 ; yt <= y2 ; yt++)  /* y loop */
  929.     #if defined(EGAGRAF)
  930.       setbyte(x1, yt, color, 0xff);  /* set whole byte */
  931.     #else
  932.       setbyte(x1, yt, color);
  933.     #endif
  934.     for( ; xt ; x1++, xt--)  /* draw after 8-bit boundery */
  935.       for(yt = y1 ; yt <= y2 ; yt++)
  936.     #if defined(EGAGRAF)
  937.       qsetpix(x1, yt, color);
  938.     #else
  939.       setpixel(x1, yt, color);
  940.     #endif
  941.     }
  942.   else
  943.     { /* less than 10 bit - use normal algorithm */
  944.   #endif
  945.     for( ; x1 <= x2 ; x1++)    /* x loop */
  946.       for(yt = y1 ; yt <= y2 ; yt++)  /* y loop */
  947.     #if defined(EGAGRAF)
  948.     qsetpix(x1, yt, color);
  949.     #else
  950.     setpixel(x1, yt, color);
  951.     #endif
  952.   #if defined(HERCGRAF) || defined(EGAGRAF)
  953.     }
  954.   #endif
  955.   #if defined(EGAGRAF)
  956.   rsestdwm();
  957.   #endif
  958.   }
  959. }
  960.  
  961.  
  962. void    circle(x, y, radius, color, aspect)
  963. register int x, y;
  964. int radius;
  965. int color;
  966. double aspect;
  967. /**
  968. * name          circle
  969. *
  970. * synopsis      circle(x, y, radius, color, aspect)
  971. *               int x, y;              center coordinate
  972. *               int radius;            circle radius
  973. *               int color;             circle color
  974. *               double aspect;         aspect ratio
  975. *
  976. * description   This function draws a circle.
  977. **/
  978. {
  979. long asp;                /* use internal long - its faster */
  980. unsigned int invrad;     /* inverse radius - grows form 0 to radius/2 */
  981. int decision;            /* controls decrement of radius */
  982. int tmp;                 /* temporary to modify desicion */
  983. unsigned long offs;      /* compute y-offset */
  984. unsigned int offsi;      /* result y-offset (faster then long!) */
  985. unsigned int round;      /* used to round (y * asp) / 256 */
  986.  
  987. if(!radius)         /* gets improved in next release    */
  988.     return;
  989. if(writemod != WM_NORM)
  990.   {
  991.   curcolor = color;
  992.   fcircle(x, y, radius, aspect);
  993.   }
  994. else
  995.   {
  996.   #if defined(EGAGRAF)
  997.   setewm2();
  998.   #endif
  999.   asp = (long) (aspect * 256);   /* using long is much faster! */
  1000.   invrad = 0;
  1001.   decision = 3 - (radius << 1);
  1002.   while(invrad <= radius)
  1003.     {
  1004.     offs = radius * asp;
  1005.     round = ((unsigned int) (offs & 0x00000080)) >> 7;
  1006.     offsi = (unsigned int) ((offs >> 8) + round); /* divide by 256 (rounded) */
  1007.     #if defined(EGAGRAF)
  1008.     qsetpix(x + invrad, y + offsi, color);
  1009.     qsetpix(x + invrad, y - offsi, color);
  1010.     qsetpix(x - invrad, y - offsi, color);
  1011.     qsetpix(x - invrad, y + offsi, color);
  1012.     #else
  1013.     setpixel(x + invrad, y + offsi, color);
  1014.     setpixel(x + invrad, y - offsi, color);
  1015.     setpixel(x - invrad, y - offsi, color);
  1016.     setpixel(x - invrad, y + offsi, color);
  1017.     #endif
  1018.     offs = invrad * asp;
  1019.     round = ((unsigned int) (offs & 0x00000080)) >> 7;
  1020.     offsi = (unsigned int) ((offs >> 8) + round); /* divide by 256 (rounded) */
  1021.     #if defined(EGAGRAF)
  1022.     qsetpix(x + radius, y + offsi, color);
  1023.     qsetpix(x + radius, y - offsi, color);
  1024.     qsetpix(x - radius, y - offsi, color);
  1025.     qsetpix(x - radius, y + offsi, color);
  1026.     #else
  1027.     setpixel(x + radius, y + offsi, color);
  1028.     setpixel(x + radius, y - offsi, color);
  1029.     setpixel(x - radius, y - offsi, color);
  1030.     setpixel(x - radius, y + offsi, color);
  1031.     #endif
  1032.     if(decision >= 0)  /* decrement radius? */
  1033.       {
  1034.       tmp = ((invrad - radius) << 2) + 10;
  1035.       radius--;
  1036.       }
  1037.     else
  1038.       tmp = (invrad << 2) + 6;
  1039.     decision += tmp;
  1040.     invrad++;
  1041.     }
  1042.   #if defined(EGAGRAF)
  1043.   rsestdwm();
  1044.   #endif
  1045.   }
  1046. }
  1047.  
  1048.  
  1049. /**
  1050. * The following static variables are used by the paint-function as
  1051. * a generall communication buffer between her und her subroutines. This
  1052. * saves stack-space because of the recursive calls.
  1053. **/
  1054. static int pcolor;        /* paint color  */
  1055. static int bcolor;        /* border color */
  1056.  
  1057. void paint(x, y, paintclr, border)
  1058. int x, y;
  1059. int paintclr;
  1060. int border;
  1061. /**
  1062. * name          paint
  1063. *
  1064. * synopsis      paint(x, y, paintclr, border)
  1065. *               int x, y;              coordinate of a point within the area
  1066. *               int paintclr;          the color used to paint
  1067. *               int border;            is the color of the border defining the
  1068. *                                      area
  1069. *
  1070. * description   This function paints an area. The area is defined by a border
  1071. *               of a specified color ("border") and the coordinate of one
  1072. *               pixel within the area (x, y). The color used to paint is
  1073. *               given in "paintclr".
  1074. *               This function ueses several subroutines and a recursive
  1075. *               algorithm! It's only the "initializer", the main work is
  1076. *               performed by the other Routines.
  1077. **/
  1078. {
  1079. pcolor = paintclr;  /* Initialize static variables */
  1080. bcolor = border;
  1081. #if defined(EGAGRAF)
  1082. setewm2();
  1083. #endif
  1084. paintfil(x, y);     /* start recursive algorithms */
  1085. #if defined(EGAGRAF)
  1086. rsestdwm();
  1087. #endif
  1088. }
  1089.  
  1090. static paintfil(x, y)
  1091. int x, y;
  1092. /**
  1093. * name          paintfil
  1094. *
  1095. * synopsis      paintfil(x, y);
  1096. *               int x, y;              coordinate of a point to process
  1097. *
  1098. * description   This function is only internal to paint, and such ist subject
  1099. *               to change without notice!
  1100. *               This is the main painting algorithm. It's called recursively
  1101. *               every new cycle.
  1102. **/
  1103. {
  1104. int x_right;
  1105. int x_left;
  1106. static int color;     /* red pixelcolor (by getpixel) */
  1107.  
  1108. /*
  1109.  * name          fillnew
  1110.  *
  1111.  * synopsis      paintfil(x, y, x_min);
  1112.  *               int x, y;
  1113.  *               int x_min;
  1114.  *
  1115.  * description   Select new fill area. This was macro was in the first release
  1116.  *               of the library a function. But the whole procedure paint()
  1117.  *               need so a lot of stack space, that it is now implemented as
  1118.  *               a macro, saving 2 Byte (or 4 Byte in the large model) of
  1119.  *               stack space per call. This reduces space requirements dra-
  1120.  *               matically. In addition 2 Byte stack space are now freed,
  1121.  *               which were previously allocated to the auto variable color,
  1122.  *               which is now common to paintfil and fillnew (it's now static,
  1123.  *               too).
  1124.  *
  1125.  * warning       because it's now a macro, there should be no side-effects in
  1126.  *               the function arguments!
  1127.  */
  1128. static int fillnewx;
  1129. #if defined(EGAGRAF)
  1130.   #define fillnew(x,y,x_min)\
  1131.   {\
  1132.   fillnewx = (x);\
  1133.   while(fillnewx >= (x_min))\
  1134.     {\
  1135.     color = qgetpix(fillnewx, (y));\
  1136.     if((color != pcolor) && (color != bcolor))\
  1137.       fillnewx = paintfil(fillnewx, (y));\
  1138.     fillnewx--;\
  1139.     }\
  1140.   }
  1141. #else /* EGAGRAF not defined */
  1142.   #define fillnew(x,y,x_min)\
  1143.   {\
  1144.   fillnewx = (x);\
  1145.   while(fillnewx >= (x_min))\
  1146.     {\
  1147.     color = getpixel(fillnewx, (y));\
  1148.     if((color != pcolor) && (color != bcolor))\
  1149.       fillnewx = paintfil(fillnewx, (y));\
  1150.     fillnewx--;\
  1151.     }\
  1152.   }
  1153. #endif
  1154.  
  1155. x_right = x_left = x;
  1156. #if defined(EGAGRAF)
  1157. qsetpix(x, y, pcolor);
  1158. #else
  1159. setpixel(x, y, pcolor);
  1160. #endif
  1161. while((++x_right) <= X_HIGH)
  1162.   {
  1163.   #if defined(EGAGRAF)
  1164.   color = qgetpix(x_right, y);
  1165.   #else
  1166.   color = getpixel(x_right, y);
  1167.   #endif
  1168.   if((color == pcolor) || (color == bcolor))
  1169.     break;  /* exit loop */
  1170.   }
  1171. x_right--;
  1172. while((--x_left) >= X_LOW)
  1173.   {
  1174.   #if defined(EGAGRAF)
  1175.   color = qgetpix(x_left, y);
  1176.   #else
  1177.   color = getpixel(x_left, y);
  1178.   #endif
  1179.   if((color == pcolor) || (color == bcolor))
  1180.     break;  /* exit loop */
  1181.   }
  1182. x_left++;
  1183. hline(x_left,x_right,y,pcolor);  /* fill area */
  1184. if(--y >= Y_LOW)
  1185.   fillnew(x_right, y, x_left);
  1186. y += 2;
  1187. if(y <= Y_HIGH)
  1188.   fillnew(x_right, y, x_left);
  1189. return(x_left);
  1190. #undef fillnew  /* local to paintfil */
  1191. }
  1192.  
  1193.  
  1194. #ifdef USEVOID
  1195. void
  1196. #endif
  1197. ellipsis(x, y, rx, ry, ws, we, color)
  1198. int x, y;
  1199. int rx, ry;
  1200. int ws, we;
  1201. int color;
  1202. /**
  1203. * name          ellipsis
  1204. *
  1205. * synopsis      ellipsis(x, y, rx, ry, ws, we, color)
  1206. *               int x, y      center coordinate
  1207. *               int rx        x - 'radius'
  1208. *               int ry        y - 'radius'
  1209. *               int ws        begin angle 0..360
  1210. *               int we        end  angle 0..360
  1211. *               int color     line color
  1212. *
  1213. * description   This function draws any sort of ellipsis. It is often called
  1214. *               circle, but I think this name should better be reserverd for
  1215. *               a function, which only draws a FULL circle (see above).
  1216. *               This function may not only draw a circle or any possible
  1217. *               ellipsis, it is also capable of drawing only parts of them.
  1218. *               This feature is often used in pie-charts. Because of its
  1219. *               great flexibility, this function ist much slower than circle.
  1220. *               If you only want a full circle (or ellipsis) you should call
  1221. *               circle.
  1222. **/
  1223. {
  1224. #define round(x) (int) (x + .5)
  1225. int w;
  1226. int drawlin;
  1227. float begarc, endarc;
  1228. float wb;
  1229. float step;
  1230.  
  1231. drawlin = 0;
  1232. if(rx < 0)
  1233.   rx = -rx;
  1234. if(ry < 0)
  1235.   ry = -ry;
  1236. if(ws < 0)
  1237.   {
  1238.   ws = -ws;
  1239.   drawlin = -1;
  1240.   }
  1241. while(ws > 360)
  1242.   ws = ws - 360;
  1243. if(we < 0)
  1244.   {
  1245.   we = -we;
  1246.   drawlin = -1;
  1247.   }
  1248. while(we > 360)
  1249.   we = we - 360;
  1250. if(ws > we)
  1251.   {
  1252.   w = ws;
  1253.   ws = we;
  1254.   we = w;
  1255.   }
  1256. step = (float) (rx + ry) / 50.0;
  1257. begarc = ws * step;        /* beginning angle */
  1258. endarc = we * step;        /* ending angle */
  1259. step = PI_D_180 / step;   /* compute new step (radiant) */
  1260. begarc = step * begarc;    /* beginning angle in radiant */
  1261. endarc = step * endarc;    /* ending angle in radiant */
  1262. for(wb = begarc ; wb <= endarc ; wb += step)
  1263.   setpixel(round(x + rx * cos(wb)), round(y - ry * sin(wb)), color);
  1264. if(drawlin && !(ws == 0 && we == 360)) /* must draw line? */
  1265.   {                                    /* Yes!            */
  1266.   line(round(x + rx * cos(begarc)), round(y - ry * sin(begarc)), x, y, color);
  1267.   line(round(x + rx * cos(endarc)), round(y - ry * sin(endarc)), x, y, color);
  1268.   }
  1269. }
  1270.  
  1271.  
  1272. #ifdef USEVOID
  1273. void
  1274. #endif
  1275. fellipsis(x, y, rx, ry, ws, we, color)
  1276. int x, y;
  1277. int rx, ry;
  1278. int ws, we;
  1279. int color;
  1280. /*
  1281.  * name          fellipsis
  1282.  *
  1283.  * synopsis      fellipsis(x, y, rx, ry, ws, we, color)
  1284.  *               int x, y      center coordinate
  1285.  *               int rx        x - 'radius'
  1286.  *               int ry        y - 'radius'
  1287.  *               int ws        begin angle 0..360
  1288.  *               int we        end  angle 0..360
  1289.  *               int color     line color
  1290.  *
  1291.  * description   This function is much like ellipsis(), but it's faster because
  1292.  *         it useses only full angles to draw the ellipsis. For a
  1293.  *         description see under ellipsis.
  1294.  */
  1295. {
  1296. register int w;
  1297. int drawlin;
  1298.  
  1299. drawlin = 0;
  1300. if(rx < 0)
  1301.   rx = -rx;
  1302. if(ry < 0)
  1303.   ry = -ry;
  1304. if(ws < 0)
  1305.   {
  1306.   ws = -ws;
  1307.   drawlin = -1;
  1308.   }
  1309. while(ws > 360)
  1310.   ws = ws - 360;
  1311. if(we < 0)
  1312.   {
  1313.   we = -we;
  1314.   drawlin = -1;
  1315.   }
  1316. while(we > 360)
  1317.   we = we - 360;
  1318. if(ws > we)
  1319.   {
  1320.   w = ws;
  1321.   ws = we;
  1322.   we = w;
  1323.   }
  1324. for(w = ws ; w <= we ; ++w)
  1325.   setpixel(round(x + rx * intcos(w)), round(y - ry * intsin(w)), color);
  1326. if(drawlin && !(ws == 0 && we == 360)) /* must draw line? */
  1327.   {                                    /* Yes!            */
  1328.   line(round(x + rx * intcos(ws)), round(y - ry * intsin(ws)), x, y, color);
  1329.   line(round(x + rx * intcos(we)), round(y - ry * intsin(we)), x, y, color);
  1330.   }
  1331. }
  1332.  
  1333.  
  1334.  
  1335. #ifdef USEVOID
  1336. void
  1337. #endif
  1338. setgloco(x_beg, y_beg, x_end, y_end)
  1339. double x_beg, y_beg;
  1340. double x_end, y_end;
  1341. /**
  1342. * name          setgloco
  1343. *
  1344. * synopsis      setgloco(x_beg, y_beg, x_end, y_end)
  1345. *               double x_beg, y_beg    minimum coordinates values
  1346. *               double x_end, y_end    maximum coordinates values
  1347. *
  1348. * description   This function initializes the global/local coordinate
  1349. *               system. This system allows you to adress your pixels based
  1350. *               on a global coordinate system. This system is independet
  1351. *               from the hardware coordinate system. Global coordinates
  1352. *               may be converted to local coordinates, wich are to be used
  1353. *               to adress the hardware.
  1354. *               So your application hasn't to look at the present video
  1355. *               hardware but use always a hardware independent own coordinate
  1356. *               system.
  1357. *               In addition you may use floats, not only integers as
  1358. *               coordinates. This is a great advantage in numerical
  1359. *               applications.
  1360. * caution       This function initilizes the system, so any call to the
  1361. *               convert routines will return grabbage, until this funtion
  1362. *               is called!
  1363. **/
  1364. {
  1365. float t;           /* temporary storage   */
  1366.  
  1367. x_start = x_beg;  /* set static variables */
  1368. y_start = y_beg;
  1369. t = x_end - x_start;
  1370. glo_maxx = ((t < 0) ? -t : t) + 1.5;      /* compute maximum x resoultion */
  1371. x_step = (float) MAX_X / (t + ((t < 0) ? -1 : 1)); /* compute x step-rate */
  1372. t = y_end - y_start;
  1373. glo_maxy = ((t < 0) ? -t : t) + 1.5;      /* compute maximum y resoultion */
  1374. y_step = (float) MAX_Y / (t + ((t < 0) ? -1 : 1)); /* compute y step-rate */
  1375. }
  1376.  
  1377.  
  1378. convxco(x)
  1379. double x;
  1380. /**
  1381. * name          convxco
  1382. *
  1383. * synopsis      locx = convxco(x)
  1384. *               double x     x coordinate to convert
  1385. *               int locx     hardware x coordinate
  1386. *
  1387. * description   This function converts a global coordinate to a local,
  1388. *               hardware dependent coordinate. Its return value may be
  1389. *               directly passed to other functions.
  1390. **/
  1391. {
  1392. return((int) ((x - x_start) * x_step + .5));
  1393. }
  1394.  
  1395.  
  1396. convyco(y)
  1397. double y;
  1398. /**
  1399. * name          convyco
  1400. *
  1401. * synopsis      locy = convyco(y)
  1402. *               double y     y coordinate to convert
  1403. *               int locy     hardware y coordinate
  1404. *
  1405. * description   This function converts a global coordinate to a local,
  1406. *               hardware dependent coordinate. Its return value may be
  1407. *               directly passed to other functions.
  1408. **/
  1409. {
  1410. return((int) ((y - y_start) * y_step + .5));
  1411. }
  1412.  
  1413.  
  1414. convxdis(xdis)
  1415. double xdis;
  1416. /**
  1417. * name          convxdis
  1418. *
  1419. * synopsis      locxdist = convxdis(xdis)
  1420. *               double xdis  distance to convert
  1421. *               int locxdist hardware distance
  1422. *
  1423. * description   This function converts a global x distance to a local,
  1424. *               hardware dependent x distance. Its return value may be
  1425. *               directly passed to other functions.
  1426. **/
  1427. {
  1428. return(iabs((int) (x_step * xdis + .5)));
  1429. }
  1430.  
  1431.  
  1432. convydis(ydis)
  1433. double ydis;
  1434. /**
  1435. * name          convydis
  1436. *
  1437. * synopsis      locydist = convydis(ydis)
  1438. *               double ydis  distance to convert
  1439. *               int locydist hardware distance
  1440. *
  1441. * description   This function converts a global y distance to a local,
  1442. *               hardware dependent y distance. Its return value may be
  1443. *               directly passed to other functions.
  1444. **/
  1445. {
  1446. return(iabs((int) (y_step * ydis +.5)));
  1447. }
  1448.  
  1449.  
  1450. polyline(color, coords)
  1451. int color;
  1452. int *coords;
  1453. /*
  1454.  * name          polyline
  1455.  *
  1456.  * synopsis      ret = polyline(color, coords, ...)
  1457.  *               int ret;     0 on success, -1 otherwise.
  1458.  *               int color    color of the line
  1459.  *               int coords   coordinate list (x, y), ends with -1, -1
  1460.  *
  1461.  * description   This function draws a polyline. That means a line, which
  1462.  *               is made of multiple coordinates. You supply as many
  1463.  *               coordinates as you need to describe the line in an integer
  1464.  *               array. They must be in (x,y) order. The end of the coordinate
  1465.  *               list is indicated by the coordinate pair (-1,-1).
  1466.  *               The function starts now at the first coordinate and draws a
  1467.  *               line from this point to the second coordinate. From there it
  1468.  *               draws a line to the third coordinate and so on, until the end
  1469.  *               of coordinate list is reached. If the coordinate list is in-
  1470.  *               valid, the function returns a true (-1) result, otherwise
  1471.  *               it returns false (0). In case of an error return the graphics
  1472.  *               error variable may be examined.
  1473.  *               The line is drawn in color "color".
  1474.  */
  1475. {
  1476. int lastx, lasty;
  1477. #define ENDLIST ((*coords == -1) && (*(coords + 1) == -1))
  1478.  
  1479. gr_error = GE_OK;
  1480. if(!ENDLIST)
  1481.   {
  1482.   lastx = *coords;
  1483.   lasty = *(++coords);
  1484.   for(coords++ ; !ENDLIST ; coords++)
  1485.     {
  1486.     line(lastx, lasty, *coords, *(coords + 1), color);
  1487.     lastx = *coords;
  1488.     lasty = *(++coords);
  1489.     }
  1490.   }
  1491. else
  1492.   gr_error = GE_NOCO;
  1493. #undef ENDLIST
  1494. return((gr_error == GE_OK) ? 0 : -1);
  1495. }
  1496.  
  1497. /*
  1498.  * vi - mode line, please do not remove them
  1499.  *
  1500.  * vi: set sw=2 | set noic :
  1501.  */
  1502.